package com.mihuxiaobaigao.ai.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 仓库管理工具类
 * 提供存入和取出物品的功能，自动计算仓库体积变化
 */
public class WarehouseManagerUtils {
    private String warehouseName1;
    private String warehouseName2;
    private double warehouse1RemainingVolume;
    private double warehouse2RemainingVolume;
    private final double warehouse1TotalVolume;
    private final double warehouse2TotalVolume;

    // 物品记录（可选，用于验证）
    private final Map<String, Integer> itemCountMap = new HashMap<>();

    /**
     * 构造函数 - 传入仓库当前状态
     * @param warehouse1TotalVolume 仓库1总体积
     * @param warehouse2TotalVolume 仓库2总体积
     * @param warehouse1RemainingVolume 仓库1剩余体积
     * @param warehouse2RemainingVolume 仓库2剩余体积
     */
    public WarehouseManagerUtils(double warehouse1TotalVolume, double warehouse2TotalVolume,
                                 double warehouse1RemainingVolume, double warehouse2RemainingVolume) {
        this.warehouse1TotalVolume = warehouse1TotalVolume;
        this.warehouse2TotalVolume = warehouse2TotalVolume;
        this.warehouse1RemainingVolume = warehouse1RemainingVolume;
        this.warehouse2RemainingVolume = warehouse2RemainingVolume;

        validateVolumes();
    }
    /**
     * 存入物品
     * @param itemName 物品名称
     * @param itemVolume 单个物品体积
     * @param itemCount 物品数量
     * @return true=成功, false=失败
     */
    public Integer storeItems(String itemName, double itemVolume, int itemCount,Integer category) throws Throwable {
        try {
            // 参数验证
            if (!validateInput(itemName, itemVolume, itemCount)) {
                return -1;
            }

            double totalVolume = itemVolume * itemCount;

            // 检查总体积是否足够
            if (totalVolume > getTotalRemainingVolume()) {
                return -1;
            }

            // 使用分配算法找到最佳方案
            StoragePlan plan = null;
            if (category==-1){
                plan = findBestStoragePlan(itemName,itemVolume, itemCount);
            }else{
                plan = findBestStoragePlan(itemName,itemVolume,itemCount,category);
            }


            // 执行存储（更新剩余体积）
            executeStoragePlan(plan, itemVolume);

            // 更新物品计数（可选）
            updateItemCount(itemName, itemCount);

            return plan.getTargetWarehouse();

        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 取出物品
     * @param itemName 物品名称
     * @param itemVolume 单个物品体积
     * @param itemCount 物品数量
     * @return true=成功, false=失败
     */
    public Boolean takeOutItems(String itemName, double itemVolume, int itemCount,Integer category) throws Throwable {
        try {
            if (!validateInput(itemName, itemVolume, itemCount)) {
                return false;
            }

            // 检查库存是否足够（如果有记录）
            if (itemCountMap.containsKey(itemName)) {
                int availableCount = itemCountMap.get(itemName);
                if (availableCount < itemCount) {
                    return false;
                }
            }

            double totalVolume = itemVolume * itemCount;

            // 检查是否有足够体积可以取出（理论上应该总是足够）
            if (totalVolume > getTotalUsedVolume()) {
                return false;
            }

            TakeOutPlan plan;
            if(category==0){
                plan = new TakeOutPlan(itemCount,0);
            }else{
                plan = new TakeOutPlan(0,itemCount);
            }

            // 执行取出（更新剩余体积）
            executeTakeOutPlan(plan, itemVolume);

            // 更新物品计数（可选）
            if (itemCountMap.containsKey(itemName)) {
                int newCount = itemCountMap.get(itemName) - itemCount;
                if (newCount <= 0) {
                    itemCountMap.remove(itemName);
                } else {
                    itemCountMap.put(itemName, newCount);
                }
            }
            return true;
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 获取仓库1最新剩余体积（存入/取出后调用）
     */
    public double getWarehouse1RemainingVolume() {
        return warehouse1RemainingVolume;
    }

    /**
     * 获取仓库2最新剩余体积（存入/取出后调用）
     */
    public double getWarehouse2RemainingVolume() {
        return warehouse2RemainingVolume;
    }

    /**
     * 获取总体积使用情况
     */
    public double getTotalUsedVolume() {
        return (warehouse1TotalVolume - warehouse1RemainingVolume) +
                (warehouse2TotalVolume - warehouse2RemainingVolume);
    }

    /**
     * 获取总剩余体积
     */
    public double getTotalRemainingVolume() {
        return warehouse1RemainingVolume + warehouse2RemainingVolume;
    }

    /**
     * 获取物品数量（如果启用了记录）
     */
    public int getItemCount(String itemName) {
        return itemCountMap.getOrDefault(itemName, 0);
    }

    // ========== 私有方法 ==========

    private void validateVolumes() {
        if (warehouse1RemainingVolume < 0 || warehouse1RemainingVolume > warehouse1TotalVolume ||
                warehouse2RemainingVolume < 0 || warehouse2RemainingVolume > warehouse2TotalVolume) {
            throw new IllegalArgumentException("仓库体积数据无效");
        }
    }

    private boolean validateInput(String itemName, double itemVolume, int itemCount) {
        return itemName != null && !itemName.trim().isEmpty() &&
                itemVolume > 0 && itemCount > 0;
    }
    private StoragePlan findBestStoragePlan(String itemName,double itemVolume, int itemCount,Integer category) throws Throwable {
        double totalVolume = itemVolume * itemCount;
        if (category==1){
            boolean canStoreInWarehouse1 = totalVolume <= warehouse1RemainingVolume;
            if (!canStoreInWarehouse1) {
                return null;
            }
            return new StoragePlan(itemCount,0,itemName);
        }else if (category==2){
            boolean canStoreInWarehouse2 = totalVolume <= warehouse2RemainingVolume;
            if (!canStoreInWarehouse2) {
                return null;
            }
            return new StoragePlan(0,itemCount,itemName);
        }else {
            System.out.println("仓库号不对");
            return null;
        }
    }

    /**
     * 核心分配算法：同名物品必须全部放在一个仓库，否则拒绝存储
     */
    private StoragePlan findBestStoragePlan(String itemName, double itemVolume, int itemCount) {
        double totalVolume = itemVolume * itemCount;

        // 检查仓库1是否有足够容量
        boolean canStoreInWarehouse1 = totalVolume <= warehouse1RemainingVolume;

        // 检查仓库2是否有足够容量
        boolean canStoreInWarehouse2 = totalVolume <= warehouse2RemainingVolume;

        if (canStoreInWarehouse1 && canStoreInWarehouse2) {
            // 两个仓库都能放下，选择剩余空间更大的仓库（优化空间利用）
            if (warehouse1RemainingVolume >= warehouse2RemainingVolume) {
                System.out.println("将" + itemCount + "个" + itemName + "全部放入仓库1（空间更大）");
                return new StoragePlan(itemCount, 0, itemName);
            } else {
                System.out.println("将" + itemCount + "个" + itemName + "全部放入仓库2（空间更大）");
                return new StoragePlan(0, itemCount, itemName);
            }
        } else if (canStoreInWarehouse1) {
            // 只能放入仓库1
            System.out.println("将" + itemCount + "个" + itemName + "全部放入仓库1");
            return new StoragePlan(itemCount, 0, itemName);
        } else if (canStoreInWarehouse2) {
            // 只能放入仓库2
            System.out.println("将" + itemCount + "个" + itemName + "全部放入仓库2");
            return new StoragePlan(0, itemCount, itemName);
        } else {
            // 两个仓库都放不下
            System.out.println("❌ 无法存储: " + itemCount + "个" + itemName +
                    "（总体积" + totalVolume + "）超过两个仓库的剩余容量");
            System.out.println("仓库1剩余容量: " + warehouse1RemainingVolume);
            System.out.println("仓库2剩余容量: " + warehouse2RemainingVolume);
            return null;
        }
    }

    private void executeStoragePlan(StoragePlan plan, double itemVolume) {
        double volume1 = plan.countInWarehouse1 * itemVolume;
        double volume2 = plan.countInWarehouse2 * itemVolume;

        warehouse1RemainingVolume -= volume1;
        warehouse2RemainingVolume -= volume2;

        // 确保不会出现负数
        warehouse1RemainingVolume = Math.max(0, warehouse1RemainingVolume);
        warehouse2RemainingVolume = Math.max(0, warehouse2RemainingVolume);
    }

    private void executeTakeOutPlan(TakeOutPlan plan, double itemVolume) {
        double volume1 = plan.countFromWarehouse1 * itemVolume;
        double volume2 = plan.countFromWarehouse2 * itemVolume;

        warehouse1RemainingVolume += volume1;
        warehouse2RemainingVolume += volume2;

        // 确保不会超过总容量
        warehouse1RemainingVolume = Math.min(warehouse1TotalVolume, warehouse1RemainingVolume);
        warehouse2RemainingVolume = Math.min(warehouse2TotalVolume, warehouse2RemainingVolume);
    }

    private void updateItemCount(String itemName, int itemCount) {
        itemCountMap.put(itemName, itemCountMap.getOrDefault(itemName, 0) + itemCount);
    }

    private double getWarehouse1UsedVolume() {
        return warehouse1TotalVolume - warehouse1RemainingVolume;
    }

    private double getWarehouse2UsedVolume() {
        return warehouse2TotalVolume - warehouse2RemainingVolume;
    }

    // 内部类：存储方案
    private static class StoragePlan {
        final int countInWarehouse1;     // 分配到仓库1的物品数量
        final int countInWarehouse2;     // 分配到仓库2的物品数量
        final String itemName;           // 物品名称

        StoragePlan(int count1, int count2, String itemName) {
            this.countInWarehouse1 = count1;
            this.countInWarehouse2 = count2;
            this.itemName = itemName;
        }

        /**
         * 获取存储的仓库编号（1或2）
         */
        public int getTargetWarehouse() {
            if (countInWarehouse1 > 0) {
                return 1;
            } else if (countInWarehouse2 > 0) {
                return 2;
            } else {
                return 0; // 未分配
            }
        }

        /**
         * 判断是否成功分配
         */
        public boolean isValid() {
            return (countInWarehouse1 > 0 || countInWarehouse2 > 0) &&
                    (countInWarehouse1 == 0 || countInWarehouse2 == 0);
        }
    }

    // 内部类：取出方案
    private static class TakeOutPlan {
        final int countFromWarehouse1;
        final int countFromWarehouse2;

        TakeOutPlan(int count1, int count2) {
            this.countFromWarehouse1 = count1;
            this.countFromWarehouse2 = count2;
        }
    }
}
